﻿package frEngine.math
{
    import __AS3__.vec.*;
    import flash.geom.*;

    public class FrMatrix3DUtils extends Object
    {
        public static const RAW_DATA_CONTAINER:Vector.<Number> = new Vector.<Number>(16);
        public static const RAW_DATA_TO_Matrix3d:Vector.<Number> = get_Raw_data();
        private static var toLeftHandleMat:Matrix3D;
        private static var toLeftHandleMatInv:Matrix3D;
        private static var _rotationQuat:Quaternion;
        private static var _rotationQuat2:Quaternion;
        private static var _toLeftHandQuat:Quaternion;
        private static var _maxToGameMatrix:Matrix3D;
        private static var _maxToGameInvMatrix:Matrix3D;

        public function FrMatrix3DUtils()
        {
            return;
        }// end function

        public static function getMaxToGameRotation() : Quaternion
        {
            var _loc_1:Quaternion = null;
            var _loc_2:Quaternion = null;
            if (_rotationQuat == null)
            {
                _rotationQuat = new Quaternion();
                _loc_1 = new Quaternion();
                _loc_2 = new Quaternion();
                _loc_1.fromAxisAngle(Vector3D.X_AXIS, (-Math.PI) * 0.5);
                _loc_2.fromAxisAngle(Vector3D.Y_AXIS, Math.PI * 0.5);
                _rotationQuat.multiply(_loc_2, _loc_1);
            }
            return _rotationQuat;
        }// end function

        private static function get_Raw_data() : Vector.<Number>
        {
            var _loc_1:* = new Vector.<Number>(16);
            _loc_1[3] = 0;
            _loc_1[7] = 0;
            _loc_1[11] = 0;
            _loc_1[12] = 0;
            _loc_1[13] = 0;
            _loc_1[14] = 0;
            _loc_1[15] = 1;
            return _loc_1;
        }// end function

        public static function getMaxToGameRotation2() : Quaternion
        {
            var _loc_1:Quaternion = null;
            var _loc_2:Quaternion = null;
            if (_rotationQuat2 == null)
            {
                _rotationQuat2 = new Quaternion();
                _loc_1 = new Quaternion();
                _loc_2 = new Quaternion();
                _loc_1.fromAxisAngle(Vector3D.X_AXIS, (-Math.PI) * 0.5);
                _loc_2.fromAxisAngle(Vector3D.Y_AXIS, (-Math.PI) * 0.5);
                _rotationQuat2.multiply(_loc_2, _loc_1);
            }
            return _rotationQuat2;
        }// end function

        public static function getMaxToGameInvMatrix() : Matrix3D
        {
            var _loc_1:Quaternion = null;
            if (_maxToGameInvMatrix == null)
            {
                _loc_1 = getMaxToGameRotation();
                _maxToGameInvMatrix = _loc_1.toMatrix3D();
                _maxToGameInvMatrix.invert();
            }
            return _maxToGameInvMatrix;
        }// end function

        public static function getMaxToGameMatrix() : Matrix3D
        {
            var _loc_1:Quaternion = null;
            var _loc_2:Matrix3D = null;
            if (_maxToGameMatrix == null)
            {
                _loc_1 = getMaxToGameRotation();
                _maxToGameMatrix = _loc_1.toMatrix3D();
                _loc_2 = getToLeftHandleMatrix();
                _maxToGameMatrix.append(_loc_2);
            }
            return _maxToGameMatrix;
        }// end function

        public static function getToLeftHandleMatrix() : Matrix3D
        {
            if (toLeftHandleMat)
            {
                return toLeftHandleMat;
            }
            toLeftHandleMat = new Matrix3D();
            toLeftHandleMat.identity();
            toLeftHandleMat.appendScale(1, 1, -1);
            return toLeftHandleMat;
        }// end function

        public static function getToLeftHandleMatInverse() : Matrix3D
        {
            if (toLeftHandleMatInv)
            {
                return toLeftHandleMatInv;
            }
            toLeftHandleMatInv = toLeftHandleMat.clone();
            toLeftHandleMatInv.invert();
            return toLeftHandleMatInv;
        }// end function

        public static function quaternion2matrix(param1:Quaternion, param2:Matrix3D = null) : Matrix3D
        {
            var _loc_3:* = param1.x;
            var _loc_4:* = param1.y;
            var _loc_5:* = param1.z;
            var _loc_6:* = param1.w;
            var _loc_7:* = _loc_3 * _loc_3;
            var _loc_8:* = _loc_3 * _loc_4;
            var _loc_9:* = _loc_3 * _loc_5;
            var _loc_10:* = _loc_3 * _loc_6;
            var _loc_11:* = _loc_4 * _loc_4;
            var _loc_12:* = _loc_4 * _loc_5;
            var _loc_13:* = _loc_4 * _loc_6;
            var _loc_14:* = _loc_5 * _loc_5;
            var _loc_15:* = _loc_5 * _loc_6;
            var _loc_16:* = RAW_DATA_TO_Matrix3d;
            _loc_16[0] = 1 - 2 * (_loc_11 + _loc_14);
            _loc_16[1] = 2 * (_loc_8 + _loc_15);
            _loc_16[2] = 2 * (_loc_9 - _loc_13);
            _loc_16[4] = 2 * (_loc_8 - _loc_15);
            _loc_16[5] = 1 - 2 * (_loc_7 + _loc_14);
            _loc_16[6] = 2 * (_loc_12 + _loc_10);
            _loc_16[8] = 2 * (_loc_9 + _loc_13);
            _loc_16[9] = 2 * (_loc_12 - _loc_10);
            _loc_16[10] = 1 - 2 * (_loc_7 + _loc_11);
            if (param2)
            {
                param2.copyRawDataFrom(_loc_16);
                return param2;
            }
            return new Matrix3D(_loc_16);
        }// end function

        public static function getForward(param1:Matrix3D, param2:Vector3D = null) : Vector3D
        {
            param2 = param2 || new Vector3D(0, 0, 0);
            param1.copyColumnTo(2, param2);
            param2.normalize();
            return param2;
        }// end function

        public static function getUp(param1:Matrix3D, param2:Vector3D = null) : Vector3D
        {
            param2 = param2 || new Vector3D(0, 0, 0);
            param1.copyColumnTo(1, param2);
            param2.normalize();
            return param2;
        }// end function

        public static function getRight(param1:Matrix3D, param2:Vector3D = null) : Vector3D
        {
            param2 = param2 || new Vector3D(0, 0, 0);
            param1.copyColumnTo(0, param2);
            param2.normalize();
            return param2;
        }// end function

        public static function compare(param1:Matrix3D, param2:Matrix3D) : Boolean
        {
            var _loc_3:* = FrMatrix3DUtils.RAW_DATA_CONTAINER;
            var _loc_4:* = param2.rawData;
            param1.copyRawDataTo(_loc_3);
            var _loc_5:uint = 0;
            while (_loc_5 < 16)
            {
                
                if (_loc_3[_loc_5] != _loc_4[_loc_5])
                {
                    return false;
                }
                _loc_5 = _loc_5 + 1;
            }
            return true;
        }// end function

        public static function lookAt(param1:Matrix3D, param2:Vector3D, param3:Vector3D, param4:Vector3D) : void
        {
            var _loc_5:Vector3D = null;
            var _loc_6:Vector3D = null;
            var _loc_7:Vector3D = null;
            var _loc_8:* = RAW_DATA_CONTAINER;
            _loc_7 = param3.crossProduct(param4);
            _loc_7.normalize();
            _loc_6 = _loc_7.crossProduct(param3);
            _loc_6.normalize();
            _loc_5 = param3.clone();
            _loc_5.normalize();
            _loc_8[0] = _loc_7.x;
            _loc_8[1] = _loc_6.x;
            _loc_8[2] = -_loc_5.x;
            _loc_8[3] = 0;
            _loc_8[4] = _loc_7.y;
            _loc_8[5] = _loc_6.y;
            _loc_8[6] = -_loc_5.y;
            _loc_8[7] = 0;
            _loc_8[8] = _loc_7.z;
            _loc_8[9] = _loc_6.z;
            _loc_8[10] = -_loc_5.z;
            _loc_8[11] = 0;
            _loc_8[12] = -_loc_7.dotProduct(param2);
            _loc_8[13] = -_loc_6.dotProduct(param2);
            _loc_8[14] = _loc_5.dotProduct(param2);
            _loc_8[15] = 1;
            param1.copyRawDataFrom(_loc_8);
            return;
        }// end function

    }
}
